import os
import sys
import json
from urllib.request import urlopen
from urllib.parse import urlencode

import psycopg2
from pytdx.errors import TdxConnectionError
from pytdx.hq import TdxHq_API

dirname = os.path.dirname(__file__)
plugin_path = os.path.join(dirname, 'venv', 'Lib', 'site-packages', 'PyQt5', 'Qt5', 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from objdict import ObjDict
from collections import namedtuple
from bak import tabWidget


class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)
        self.jsonUnit = jsonUnit()
        self.jsonFile = "./stockSetting.json"
        self.settingJson = self.jsonUnit.readJsonFile(self.jsonFile)
        self.ui = tabWidget.Ui_Window()
        self.ui.setupUi(self)
        self.ui.retranslateUi(self)
        self.connectChange()

    def do_timer_timeout(self):  # 定时中断相应
        curTime = QDateTime.currentDateTime()  # 获取当前时间
        timePlay = curTime.toString('yyyy-MM-dd dddd hh:mm:ss')
        self.ui.dateTimeLabel.setText(timePlay)

    def connectChange(self):
        self.timer = QTimer()  # 创建定时器
        self.timer.start(1000)  # 定时周期1000ms
        self.timer.timeout.connect(self.do_timer_timeout)
        self.ui.logoutButton.clicked.connect(self.close)    # 退出关闭按钮
        self.ui.getStockListButton.clicked.connect(self.getStockList)
        self.ui.selectPathButton.clicked.connect(self.pathSelected)
        self.ui.APITestButton.clicked.connect(self.tdxAPIText)
        self.ui.DBTestButton.clicked.connect(self.pgsqlConnectText)
        self.ui.saveSettingButton.clicked.connect(self.saveSetting)
        self.ui.tabWidget.currentChanged.connect(self.tabBarChanged)

    def tabBarChanged(self):
        if self.ui.tabWidget.tabBar().currentIndex() == 3 or self.ui.tabWidget.tabBar().currentIndex() == 4:
            self.loadSetting()

    def getStockList(self):
        url = 'http://api.k780.com'
        params = {
            'app': 'finance.stock_list',
            'category': 'hs',
            'appkey': '53102',
            'sign': 'e5e7829786db6eb56e5fb51190f571d8',
            'format': 'json',
        }
        params = urlencode(params)
        try:
            conn = psycopg2.connect(
                database=self.ui.dbNameEdit.text(),
                user=self.ui.dbUserEdit.text(),
                password=self.ui.dbPasswordEdit.text(),
                host=self.ui.dbAddressEdit.text(),
                port=self.ui.dbPortSpinBox.value()
            )
            cursor = conn.cursor()
            f = urlopen('%s?%s' % (url, params))
            nowapi_call = f.read()
            result = json.loads(nowapi_call)
            if result:
                if result['success'] != '0':
                    for o in result['result']['lists']:
                        cursor.execute("INSERT INTO trading.stock(stock_code, stock_label, stock_market) "
                                       "VALUES ('%s', '%s', '%s')" % (o['symbol'][2:], o['sname'], o['symbol'][0:2]))
                else:
                    QMessageBox.warning(self, "操作失败", "获取API操作失败: " + result['msgid'] + ' ' + result['msg'])
            else:
                QMessageBox.warning(self, "操作失败", "请求http://www.nowapi.com操作失败！")
        except Exception as e:
            print('报错：' + str(e))
            QMessageBox.warning(self, "操作失败", "获取证券列表操作失败！")
        else:
            QMessageBox.about(self, "操作成功", "获取证券列表操作成功！")
        finally:
            conn.commit()
            conn.close()

    def pathSelected(self):
        path = QFileDialog.getExistingDirectory(self, "选择文件夹")
        self.ui.tdxPathEdit.setText(path)

    def tdxAPIText(self):
        api = TdxHq_API(raise_exception=True)
        try:
            api.connect(self.ui.tdxIPEdit.text(), self.ui.tdxPortSpinBox.value())
            self.ui.tdxStatusLabel.setText("连接成功！")
            api.disconnect()
        except TdxConnectionError as e:
            self.ui.tdxStatusLabel.setText("连接失败！")
            print(e)

    def pgsqlConnectText(self):
        try:
            psycopg2.connect(
                database=self.ui.dbNameEdit.text(),
                user=self.ui.dbUserEdit.text(),
                password=self.ui.dbPasswordEdit.text(),
                host=self.ui.dbAddressEdit.text(),
                port=self.ui.dbPortSpinBox.value()
            )
            self.ui.pgsqlStatusLabel.setText("连接成功！")
        except Exception as e:
            self.ui.pgsqlStatusLabel.setText("连接失败！")
            print(e)

    def loadSetting(self):
        data = self.jsonUnit.readJsonFile(self.jsonFile)
        if data is not False:
            self.ui.tdxPathEdit.setText(data.api.path)
            self.ui.tdxIPEdit.setText(data.api.ip)
            self.ui.tdxPortSpinBox.setValue(data.api.port)
            self.ui.dbAddressEdit.setText(data.pgsql.ip)
            self.ui.dbPortSpinBox.setValue(data.pgsql.port)
            self.ui.dbSchemasEdit.setText(data.pgsql.schemas)
            self.ui.dbNameEdit.setText(data.pgsql.name)
            self.ui.dbUserEdit.setText(data.pgsql.user)
            self.ui.dbPasswordEdit.setText(data.pgsql.password)
            self.ui.stockCheckBox.setChecked(data.fee.stock.check)
            self.ui.stockCerticationFeeSpinBox.setValue(data.fee.stock.certicationFee)
            self.ui.stockCommissionSpinBox.setValue(data.fee.stock.commission)
            self.ui.stockHandlingFeeSpinBox.setValue(data.fee.stock.handlingFee)
            self.ui.stockStampDutySpinBox.setValue(data.fee.stock.stampDuty)
            self.ui.stockTransferFeeSpinBox.setValue(data.fee.stock.transferFee)
            self.ui.etfCheckBox.setChecked(data.fee.etf.check)
            self.ui.etfCerticationFeeSpinBox.setValue(data.fee.etf.certicationFee)
            self.ui.etfCommissionSpinBox.setValue(data.fee.etf.commission)
            self.ui.etfHandlingFeeSpinBox.setValue(data.fee.etf.handlingFee)
            self.ui.etfStampDutySpinBox.setValue(data.fee.etf.stampDuty)
            self.ui.etfTransferFeeSpinBox.setValue(data.fee.etf.transferFee)
            self.ui.bondCheckBox.setChecked(data.fee.bond.check)
            self.ui.bondCerticationFeeSpinBox.setValue(data.fee.bond.certicationFee)
            self.ui.bondCommissionSpinBox.setValue(data.fee.bond.commission)
            self.ui.bondHandlingFeeSpinBox.setValue(data.fee.bond.handlingFee)
            self.ui.bondStampDutySpinBox.setValue(data.fee.bond.stampDuty)
            self.ui.bondTransferFeeSpinBox.setValue(data.fee.bond.transferFee)

    def saveSetting(self):
        data = ObjDict()
        data.api = ObjDict()
        data.api.path = self.ui.tdxPathEdit.text()
        data.api.ip = self.ui.tdxIPEdit.text()
        data.api.port = self.ui.tdxPortSpinBox.value()
        data.pgsql = ObjDict()
        data.pgsql.ip = self.ui.dbAddressEdit.text()
        data.pgsql.port = self.ui.dbPortSpinBox.value()
        data.pgsql.schemas = self.ui.dbSchemasEdit.text()
        data.pgsql.name = self.ui.dbNameEdit.text()
        data.pgsql.user = self.ui.dbUserEdit.text()
        data.pgsql.password = self.ui.dbPasswordEdit.text()
        data.fee = ObjDict()
        data.fee.stock = ObjDict()
        data.fee.stock.check = self.ui.stockCheckBox.isChecked()
        data.fee.stock.certicationFee = self.ui.stockCerticationFeeSpinBox.value()
        data.fee.stock.commission = self.ui.stockCommissionSpinBox.value()
        data.fee.stock.handlingFee = self.ui.stockHandlingFeeSpinBox.value()
        data.fee.stock.stampDuty = self.ui.stockStampDutySpinBox.value()
        data.fee.stock.transferFee = self.ui.stockTransferFeeSpinBox.value()
        data.fee.etf = ObjDict()
        data.fee.etf.check = self.ui.etfCheckBox.isChecked()
        data.fee.etf.certicationFee = self.ui.etfCerticationFeeSpinBox.value()
        data.fee.etf.commission = self.ui.etfCommissionSpinBox.value()
        data.fee.etf.handlingFee = self.ui.etfHandlingFeeSpinBox.value()
        data.fee.etf.stampDuty = self.ui.etfStampDutySpinBox.value()
        data.fee.etf.transferFee = self.ui.etfTransferFeeSpinBox.value()
        data.fee.bond = ObjDict()
        data.fee.bond.check = self.ui.bondCheckBox.isChecked()
        data.fee.bond.certicationFee = self.ui.bondCerticationFeeSpinBox.value()
        data.fee.bond.commission = self.ui.bondCommissionSpinBox.value()
        data.fee.bond.handlingFee = self.ui.bondHandlingFeeSpinBox.value()
        data.fee.bond.stampDuty = self.ui.bondStampDutySpinBox.value()
        data.fee.bond.transferFee = self.ui.bondTransferFeeSpinBox.value()
        self.settingJson = self.jsonUnit.writeJsonFile(self.jsonFile, data)
        return

class jsonUnit(object):
    def dict2obj(self, object):
        if isinstance(object, dict):
            return namedtuple(
                'struct', object.keys()
            )(
                *(self.dict2obj(val) for val in object.values())
            )
        elif isinstance(object, (tuple, list, set, frozenset)):
            return type(object)(self.dict2obj(_) for _ in object)
        else:
            return object

    def getKeys(self, data):
        keysAll_list = []
        def getkeys(data):  # 遍历json所有key
            if (type(data) == type({})):
                keys = data.keys()
                for key in keys:
                    value = data.get(key)
                    if (type(value) != type({}) and type(value) != type([])):
                        keysAll_list.append(key)
                    elif (type(value) == type({})):
                        keysAll_list.append(key)
                        getkeys(value)
                    elif (type(value) == type([])):
                        keysAll_list.append(key)
                        for para in value:
                            if (type(para) == type({}) or type(para) == type([])):
                                getkeys(para)
                            else:
                                keysAll_list.append(para)
        getkeys(data)
        return keysAll_list

    # 检测目标字段tagkey是否在data(json数据)中
    def isExtend(self, data, tagkey):
        if (type(data) != type({})):
            print('please input a json!')
        else:
            key_list = self.getKeys(data)
            for key in key_list:
                if (key == tagkey):
                    return True
        return False

    def readJsonFile(self, jsonFile):
        data = False
        if os.path.isfile(jsonFile):
            with open(jsonFile, 'r', encoding='utf-8') as f:
                if os.path.getsize(jsonFile) != 0:
                    data = self.dict2obj(json.load(f))
        return data

    def writeJsonFile(self, jsonFile, jsonData):
        with open(jsonFile, 'w', encoding='utf-8') as f:
            json.dump(jsonData, f, ensure_ascii=False)
        return jsonData

if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = MainWindow()
    gui.show()
    sys.exit(app.exec_())